﻿using System;
using System.Collections.Generic;
using System.Data;
using Wholesaler.Models.DBModels;
using Yunzuan.Foundation.DataAccess;
using YunZuan.Models.Entities;
using Yunzuan.Foundation.Log;
using YunZuan.Models;

namespace Yunzuan.Common
{
    public class DiamondsPriceHandlers
    { 

        public static SupplierInfo GetSuppliers(string tttagKey, string supplierCode, int SupplierType = 1)
        {
            Dictionary<string, SupplierInfo> suppliers = new Dictionary<string, SupplierInfo>();
            //supplierCode一律转大写
            supplierCode = supplierCode.ToUpper();

            try
            {
                if (System.Web.HttpContext.Current != null)
                {

                    if (System.Web.HttpContext.Current.Cache.Get("Cache:Suppliers" + tttagKey + supplierCode + SupplierType) == null)
                    {
                        GetAllSupplierListByTagKey(tttagKey, SupplierType, suppliers);
                        System.Web.HttpContext.Current.Cache["Cache:Suppliers" + tttagKey + supplierCode + SupplierType] = suppliers;

                    }
                    else
                    {
                        suppliers = (Dictionary<string, SupplierInfo>)System.Web.HttpContext.Current.Cache["Cache:Suppliers" + tttagKey + supplierCode + SupplierType];

                    }
                }
                else
                {
                    GetAllSupplierListByTagKey(tttagKey, SupplierType, suppliers);
                }

            }
            catch (Exception ex)
            {
                //GetMethodInfoAndWriteLogs(typeof(DiamondsPriceHandler), ex, "获取供应商错误");
                throw;
                //供应商报错 9-27
            }
            if (suppliers.ContainsKey(supplierCode))
                return suppliers[supplierCode];
            else
                //供应商不存在
                return new SupplierInfo { Rebate = 0, FancyRebate = 0, GemRebate = 1, RingRebate = 1, ParcelRebate = 1, EmeraldRebate = 1, ShipTime = "" };
        }

        private static void GetAllSupplierListByTagKey(string tttagKey, int SupplierType, Dictionary<string, SupplierInfo> suppliers)
        {
            PageParam param = new PageParam();

            param.PageIndex = 1;
            param.PageSize = 9999;//内置9999家
            param.Add("SupplierType", SupplierType);
            //获取供应商信息 9-27
            PageList<SupplierInfo> result = YZ.GetDatabase(tttagKey).QueryForList<SupplierInfo>("Supplier.GetList", param, param.PageSize, param.PageIndex);

            foreach (var item in result.Data)
            {
                if (!item.Rebate.HasValue) { item.Rebate = 0; }
                if (!item.FancyRebate.HasValue) { item.FancyRebate = 0; }
                if (!item.GemRebate.HasValue) { item.GemRebate = 1; }
                if (!item.RingRebate.HasValue) { item.RingRebate = 1; }
                if (!item.ParcelRebate.HasValue) { item.ParcelRebate = 1; }
                if (!item.EmeraldRebate.HasValue) { item.EmeraldRebate = 1; }
                if (!item.InlaySettingsRebate.HasValue) { item.InlaySettingsRebate = 1; }
                suppliers[item.SupplierCode.ToUpper()] = item;//一律转成大写SupplierCode
            }
        }

        /// <summary>
        /// 计算价格 - 裸钻 Loose Diamond
        /// </summary>
        /// <param name="item"></param>
        /// <param name="customer"></param>
        /// <param name="setting"></param>
        public void ComputePrice(InventoryInfoResult item, CustomerInfo customer, SysSettingInfo setting, string key, string secondSn = "")
        {

            if (item == null)
            {
                return;
            }
            try
            {
                if (item.ShipTime != null && item.ShipTime.IndexOf("1970") > -1) //如果是初始值 ，则使用供应商的设置
                {
                    item.ShipTime = GetSuppliers(key, item.Supplier).ShipTime;
                }
                if (item.ShipTime != null && item.ShipTime.IndexOf("1970") > -1) //如果是初始值 ，则使用供应商的设置
                {
                    item.ShipTime = "";
                }
                if (item.PurchaseTime != null && item.PurchaseTime.IndexOf("1970") > -1) //如果是初始值 ，则使用供应商的设置
                {
                    item.PurchaseTime = "";
                }
                if (item.ArrivalTime != null && item.ArrivalTime.IndexOf("1970") > -1) item.ArrivalTime = "";
                decimal sourceDisc = 0;//临时退点
                decimal tempDouble = 1; //临时存储白或彩的倍率
                //彩钻
                if (item.IsFancy == 1)
                {
                    //分析4c折扣-彩钻
                    IList<Group_Amount> lv2FancyDiss = GetGroupAmount(2, setting.GroupAmount, key); //计算价格分组的倍率集合

                    //分组彩
                    if (lv2FancyDiss != null)
                    {
                        foreach (var item2 in lv2FancyDiss)
                        {
                            if (item.SourceDolarPerGrain >= item2.MinAmount && item.SourceDolarPerGrain <= item2.MaxAmount)
                            {
                                ///分组倍率
                                if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                                    tempDouble = 1;
                                tempDouble = item2.Double == 0 ? 1 : item2.Double;
                                break;
                            }
                        }
                    }
                    decimal fancyRebate = 0;
                    if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                    {
                        fancyRebate = 0;
                    }
                    else
                    {
                        fancyRebate = GetSuppliers(key, item.Supplier).FancyRebate.Value;
                    }
                    //彩钻价格计算
                    item.DiscountReturn = fancyRebate;
                    item.DolarPerGrain = (decimal)item.SourceDolarPerGrain * (decimal)((100 + fancyRebate) / 100) * tempDouble; //只在粒上乘以倍率
                    item.DolarPerCarat = item.DolarPerGrain / (decimal)item.Weight;
                    item.RMBPerGrain = item.DolarPerGrain * GoodsType.GetRate(setting); //只在粒上乘以倍率
                    item.RMBPerCarat = item.RMBPerGrain / (decimal)item.Weight;
                    item.SourceDolarPerCarat = Math.Round(item.SourceDolarPerGrain.Value / Convert.ToDecimal(item.Weight), 1, MidpointRounding.AwayFromZero);
                    if (customer != null)
                    {
                        decimal customerFancyRebate = 1;
                        if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                        {
                            customerFancyRebate = 1;
                        }
                        else
                        {
                            customerFancyRebate = customer.FancyRebate.Value;
                        }
                        item.CustomerDolarPerGrain = item.DolarPerGrain * customerFancyRebate; //只在美金单粒上乘以客户折扣
                        item.CustomerDolarPerCarat = item.CustomerDolarPerGrain.Value / Convert.ToDecimal(item.Weight);
                        item.CustomerRMBPerGrain = item.CustomerDolarPerGrain * GoodsType.GetRate(setting); //只在粒上乘以倍率;
                        item.CustomerRMBPerCarat = item.CustomerRMBPerGrain.Value / Convert.ToDecimal(item.Weight);
                    }

                }
                //白钻价格
                else
                {

                    //分析4c折扣-白钻
                    IList<Group_4C> lv2Diss = GetGroupCCCC(1, setting.Group4C, key);  //2为彩 ,1 为白//白钻分组数据(匹配成想要的格式)
                    //分组白
                    if (lv2Diss != null)
                    {
                        var shape = 0;  //存储异形或圆形
                        foreach (var item2 in lv2Diss)
                        {
                            int sha = item2.Shape == "round" ? 1 : 2; //规则

                            //item.Weight   0.31-0.36

                            decimal minWeight = item2.MinWeight;
                            decimal maxWeight = item2.MaxWeight;
                            shape = item.Shape > 1 ? 2 : 1;  //设置为圆形或者异形
                            if (shape == sha && item.Weight >= minWeight && item.Weight <= maxWeight)
                            {
                                //全局折扣+=加上分组折扣(白)
                                sourceDisc += item2.Dis;
                                tempDouble = item2.Double == 0 ? 1 : item2.Double;  //有分组倍率，则全局*分组  合并为全局倍率
                                break;
                            }
                        }
                    }
                    //原退点 +当前供应商的退点
                    sourceDisc += GetSuppliers(key, item.Supplier).Rebate.Value;

                    if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                    {
                        sourceDisc = 0;
                    }
                    sourceDisc += item.SourceDiscountReturn.Value;
                    //原退点 +当前供应商的退点 +全局退点
                    //sourceDisc += GoodsType.GetGlobalDiscountReturn(setting);
                    //discount=CalcWhiteReturnPoint(
                    item.DiscountReturn = sourceDisc;
                    //美金克拉价格
                    item.DolarPerCarat = (decimal)(item.Rapnet * ((100 + sourceDisc) / 100)) * tempDouble;
                    //美金单粒价格
                    item.DolarPerGrain = item.DolarPerCarat * (decimal)item.Weight.Value; //只在粒上乘以倍率
                    item.RMBPerCarat = item.DolarPerCarat * GoodsType.GetRate(setting);//报错？
                    item.RMBPerGrain = item.RMBPerCarat * (decimal)item.Weight.Value; //只在粒上乘以倍率


                    item.DiscountReturn = CalcWhiteReturnPoint(0, item.DolarPerGrain, item.Rapnet, item.Weight, 1, 0);

                    //客户看到的价格
                    if (customer != null)
                    {
                        //按退点计算
                        if (customer.IsRebate == 1 || customer.IsRebate == null)
                        {
                            if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                            {
                                customer.Rebate = 0;
                            }
                            //计算客户价格--白钻   //原退点 +当前供应商的退点 +全局退点+客户退点 
                            item.CustomerDolarPerCarat = (decimal)(item.Rapnet * (decimal)((100 + Convert.ToDecimal(sourceDisc) + customer.Rebate) / 100)) * tempDouble;//客户美金每卡 2017-04-01
                            item.CustomerDolarPerGrain = item.CustomerDolarPerCarat * (decimal)item.Weight.Value;//客户美金总价 2017-01-19
                            item.CustomerRMBPerCarat = item.CustomerDolarPerCarat * GoodsType.GetRate(setting);
                            //RMB单粒价格
                            item.CustomerRMBPerGrain = item.CustomerRMBPerCarat * (decimal)item.Weight.Value; //只在粒上乘以倍率

                            //美元单粒价 		= RAPNET * (100 + 相应退点) / 100 * 重量
                            item.CustomerDiscountReturn = CalcWhiteReturnPoint(0, item.CustomerDolarPerGrain, item.Rapnet, item.Weight, 1, 0);
                        }
                        else if (customer.IsRebate == 0) //倍率
                        {
                            if (item.Supplier == secondSn)//若是二级的现货需要将倍率设置为1 退点为0
                            {
                                customer.Rebate = 1;
                            }
                            item.CustomerDolarPerCarat = (decimal)(item.Rapnet * (decimal)((100 + Convert.ToDecimal(sourceDisc)) / 100)) * tempDouble * (customer.Rebate == 0 ? 1 : customer.Rebate);
                            item.CustomerDolarPerGrain = item.CustomerDolarPerCarat * (decimal)item.Weight.Value;//客户美金总价 2017-01-19
                            item.CustomerRMBPerCarat = item.CustomerDolarPerCarat * GoodsType.GetRate(setting);
                            //RMB单粒价格
                            item.CustomerRMBPerGrain = item.CustomerRMBPerCarat * (decimal)item.Weight.Value; //只在粒上乘以倍率

                            //美元单粒价 		= RAPNET * (100 + 相应退点) / 100 * 重量
                            item.CustomerDiscountReturn = CalcWhiteReturnPoint(0, item.CustomerDolarPerGrain, item.Rapnet, item.Weight, 1, 0);

                        }
                    }
                }
            }
            catch (Exception ee)
            {
                item.RMBPerGrain = 0;
                item.RMBPerCarat = 0;
                item.CustomerDiscountReturn = 0;
                item.CustomerRMBPerCarat = 0;
                item.CustomerRMBPerGrain = 0;
                item.SourceDolarPerGrain = 0;
                Logger.Warn(typeof(DiamondsPriceHandlers), "计算价格失败," + ee.Message);
            }
        }

        public static IList<Group_Amount> GetGroupAmount(int lib, string str, string key)
        {
            if (str == null || str == "" || str.Trim().Length < 1) return null;
            else
            {
                if (System.Web.HttpContext.Current.Cache.Get(key + "Cache:GroupAmount" + lib.ToString()) == null)
                {
                    str = str.TrimEnd(';');//去多组合的末尾;

                    string[] obj = str.Replace("\n", "").Replace("\r", "").Split(';');  //分组存相对应的折扣
                    IList<Group_Amount> lv2Amounts = new List<Group_Amount>();

                    //1.形状
                    for (int i = 0; i < obj.Length; i++)
                    {
                        Group_Amount lv2Amount = new Group_Amount();
                        //9999.99-#0.99#;10000-19999.99#0.89#;50000+#1.11#;
                        string[] temps = obj[i].Split('#');
                        if (temps.Length > 1)
                        {
                            //2.重量
                            if (temps[0].Contains("-"))
                            {
                                var prices = temps[0].Split('-');
                                if (prices[1] == "")//指1w以下 9999.99-
                                {
                                    lv2Amount.MaxAmount = Convert.ToDecimal(prices[0]);
                                    lv2Amount.MinAmount = Convert.ToDecimal(0);
                                }
                                else
                                {
                                    lv2Amount.MaxAmount = Convert.ToDecimal(prices[1]);
                                    lv2Amount.MinAmount = Convert.ToDecimal(prices[0]);
                                }
                            }
                            else if (temps[0].Contains("+"))//处理规则中的特殊替代字符
                            {
                                lv2Amount.MinAmount = Convert.ToDecimal(temps[0].Replace("+", ""));//处理规则中的特殊替代字符
                                lv2Amount.MaxAmount = 999999999.99M;
                            }
                            else
                            {
                                lv2Amount.MaxAmount = 999999999.99M;
                                lv2Amount.MinAmount = 0;
                            }
                            lv2Amount.Double = temps[1] == "" ? 1 : Convert.ToDecimal(temps[1]);
                            lv2Amount.Dis = temps[2] == "" ? 0 : Convert.ToDecimal(temps[2]);
                            lv2Amounts.Add(lv2Amount);
                        }
                    }
                    //第一次访问5分钟后过期，免得修改了4c或金额得改缓存设置
                    System.Web.HttpContext.Current.Cache.Insert(key + "Cache:GroupAmount" + lib.ToString(), lv2Amounts, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
                    return lv2Amounts;
                }
                else
                {
                    return System.Web.HttpContext.Current.Cache.Get(key + "Cache:GroupAmount" + lib.ToString()) as IList<Group_Amount>;
                }

            }
        }

        //分析4c折扣
        public static IList<Group_4C> GetGroupCCCC(int lib,string str,string key)
        {
            if (str == null || str == "" || str.Trim().Length < 1) return null;
            else
            {
                if (System.Web.HttpContext.Current.Cache.Get(key+"Cache:Group4C"+lib.ToString()) == null)
                {
                    str = str.TrimEnd(';');//去多组合的末尾;
                    
                    string[] obj = str.Replace("\n", "").Replace("\r", "").Split(';');  //分组存相对应的折扣
                    IList<Group_4C> lv2CCCCs = new List<Group_4C>();

                    //1.形状
                    for (int i = 0; i < obj.Length; i++)
                    {
                        Group_4C lv2CCCC = new Group_4C();
                        //round 0.30-0.39 h si1 2;
                        string[] temps = obj[i].Replace("white#", "").Replace("fancy#", "").Split('#');
                        if (temps.Length > 1)
                        {
                            lv2CCCC.Shape = temps[0];
                            //2.重量
                            if (temps[1].Contains("-")) {
                                var weights = temps[1].Split('-');
                                lv2CCCC.MinWeight =Convert.ToDecimal(weights[0]);
                                lv2CCCC.MaxWeight = Convert.ToDecimal(weights[1]);
                            }
                            else {
                                lv2CCCC.MinWeight =0.01M;
                                lv2CCCC.MaxWeight = 999.99M;
                            }
                            
                            lv2CCCC.Double = temps[2] == "" ? 1 : Convert.ToDecimal(temps[2]);
                            lv2CCCC.Dis = temps[3] == "" ? 0 : Convert.ToDecimal(temps[3]);
                            lv2CCCCs.Add(lv2CCCC);
                        }
                    }
                    //第一次访问5分钟后过期，免得修改了4c或金额得改缓存设置
                    System.Web.HttpContext.Current.Cache.Insert(key+"Cache:Group4C" + lib.ToString(), lv2CCCCs, null, System.Web.Caching.Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(5));
                    return lv2CCCCs;
                }
                else
                {
                    return System.Web.HttpContext.Current.Cache.Get(key + "Cache:Group4C" + lib.ToString()) as IList<Group_4C>;
                }
                
            }
        }

        #region 现货下载的csv或excel计算价格

        /// <summary>
        /// 计算价格 - 裸钻 Loose Diamond
        /// </summary>
        /// <param name="row"></param>
        /// <param name="customer"></param>
        /// <param name="setting"></param>
        public void ComputeCsvPrice(DataRow row, bool isFancy, decimal doubleNum, decimal disNum)
        {
            if (row == null)
            {
                return;
            }
            try
            {
                decimal sourceDisc = 0;//临时退点 
                //decimal weight = Convert.ToDecimal(row["Weight"]);
                var shape = row["Shape"].ToString().ToLower() == "round" ? 1 : 2;  //设置为圆形或者异形
                //彩钻
                if (isFancy)
                { 
                    //彩钻价格计算
                    row["Rapnet Discount %"] = "";
                    //美金克拉价格
                    //row["RapNet Price"] = (Convert.ToDecimal(row["RapNet Price"]) * doubleNum) / weight;
                    row["RapNet Price"] = (Convert.ToDecimal(row["RapNet Price"]) * doubleNum);
                }
                //白钻价格
                else
                { 
                    sourceDisc += disNum;
                    sourceDisc += Convert.ToDecimal(row["Rapnet Discount %"]);
                    row["Rapnet Discount %"] = sourceDisc;
                    //美金克拉价格
                    row["RapNet Price"] = (decimal)(Convert.ToDecimal(row["Rap"]) * ((100 + sourceDisc) / 100));
                }
            }
            catch (Exception ee)
            {
                
                Logger.Warn(typeof(DiamondsPriceHandlers), "计算价格失败," + ee.Message);
            }
        }
        #endregion

        #region 计算退点
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ConfirmUSD">美元单粒价</param>
        /// <param name="Rapnet">Rapnet</param>
        /// <param name="Weight">Weight</param>
        /// <param name="Discounts">Discounts</param>
        /// <returns></returns>
        public static decimal? CalcWhiteReturnPoint(decimal? ConfirmUSD, decimal? Rapnet, decimal? Weight, decimal? Discounts)
        {
            //美元单粒价 		= RAPNET * (100 + 相应退点) / 100 * 重量
            decimal? ReturnPoint = ConfirmUSD * Discounts / Weight * 100 / Rapnet - 100;

            return ReturnPoint;
        }
        #endregion


        #region 计算退点
        /// <summary>
        /// 
        /// </summary>
        /// <param name="ConfirmUSD">美元单粒价</param>
        /// <param name="Rapnet">Rapnet</param>
        /// <param name="Weight">Weight</param>
        /// <param name="Discounts">Discounts</param>
        /// <param name="SourceDolarPerGrain">原单粒价</param>
        /// <returns></returns>
        public static decimal? CalcWhiteReturnPoint(int IsFancy, decimal? ConfirmUSD, decimal? Rapnet, decimal? Weight, decimal? Discounts, decimal? SourceDolarPerGrain)
        {
            decimal? ReturnPoint = 0;
            if (IsFancy != 1)
            {
                //美元单粒价 		= RAPNET * (100 + 相应退点) / 100 * 重量
                ReturnPoint = ConfirmUSD * Discounts / Weight * 100 / Rapnet - 100;
            }
            else
            {
                //美元单粒价 		= 原单粒价 * (100 + 退点) / 100   
                ReturnPoint = ConfirmUSD * Discounts * 100 / SourceDolarPerGrain - 100;
            }
            return ReturnPoint;
        }
        #endregion
    }
}
